home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <exec/types.h>
- #include <intuition/intuition.h>
- #include <math.h>
- /***********************************************************************
- * Superhop.c
- *
- * This program opens a screen (using the XOpenScreen function),
- * then requests four numbers as input. The numbers are used to
- * generate a pattern as discussed in the August, 1986 Scientific
- * American article on computer recreations. After a pattern is
- * drawn, a portion of the pattern may be enlarged by selecting a
- * box with the mouse. To start a new pattern, change one or more
- * of the input numbers. To stop the program,
- * select the close window gadget.
- *
- * Note: The XOpenScreen function is described in Compute!'s Amiga
- * Programmer's Guide, and is not included here. You'll have to
- * link with your own screen open function.
- * Also, the inner-most loop uses the Motorola Fast Floating Point
- * routines, which are difficult to use from Lattice. The MyInit routine
- * uses the usual C syntax, so if you want to compile with Manx, model
- * the inner-most loop after the MyInit formulae.
- *************************************************************************/
- #define DOWN 1
- #define UP 0
-
- struct NewWindow newwindow = {
- 0, 0,
- 640, 200,
- 0, 1,
- CLOSEWINDOW | MOUSEMOVE | MOUSEBUTTONS,
- WINDOWSIZING | SIZEBRIGHT | WINDOWDEPTH | WINDOWDRAG
- | SMART_REFRESH | ACTIVATE | NOCAREREFRESH
- | WINDOWCLOSE | REPORTMOUSE,
- NULL,
- NULL,
- "Pattern Window",
- NULL,
- NULL,
- 180, 50, 640, 200,
- CUSTOMSCREEN
- };
-
- struct Window *window, *g_window;
- struct Screen *screen;
- struct GfxBase *GfxBase; /* note: the name MUST be GfxBase */
- struct IntuitionBase *IntuitionBase; /* as above */
- struct IntuiMessage *message;
- struct RastPort *DrawRP;
- struct RastPort *GadgRP;
- struct ViewPort *DrawVP;
- struct Screen *XOpenScreen();
-
- BYTE scaled = 0;
-
- void add_gadgets();
-
- /* for Manx Aztec C */
- #if MCH_AMIGA
- #include <functions.h>
- #endif
-
- int MathBase;
- int MathTransBase;
-
- typedef union { float f; int i; } FFP;
-
- float SPTieee();
- char bmath[] = "mathffp.library";
- char tmath[] = "mathtrans.library";
-
- char input[40] = "-3.14,.3,.3,10000";
- char outtext[40];
-
- main()
- {
- FFP affp, bffp, cffp, xscffp, xoffp, yoffp, f1ffp, xffp, yffp, xx, yy;
- BYTE gadgflag = 1; /* identifies when gadget window is on */
- int color = 2; /* drawing color */
- int Depth = 4; /* number of bit planes in screen */
- int class, mcode;
- FLOAT a, b, c; /* parameters used in pattern algorithm */
- FLOAT savea = 0, saveb = 0, savec = 0; /* variables for saving a,b,c */
- FLOAT f1 = 0.44; /* scaling factor */
- int i, num, dif;
- int x0 = 0, y0 = 0; /* location of dot to be drawn, in pixels */
- FLOAT x = 0, y = 0; /* location of dot to be drawn, in parameter space units */
- FLOAT xoff = 0, yoff = 0, xscale = 0; /* scale parameters */
- FLOAT xmin, xmax, ymax, ymin;
- int tlcx, tlcy; /* top left corner of box */
- int brcx, brcy; /* bottom right corner of box */
- int boxx, boxy = 0; /* corners of box while being drawn */
- BYTE boxon = 0; /* flag for when a box is being drawn */
-
- /* Open Libraries */
- if ((IntuitionBase =
- (struct IntuitionBase *)OpenLibrary("intuition.library",1)) == NULL)
- Cleanup("Error: couldn't open intuition library\n");
- if ((GfxBase =
- (struct GfxBase *)OpenLibrary("graphics.library",1)) == NULL)
- Cleanup("Error: couldn't open graphics library\n");
- if ((MathBase = OpenLibrary(bmath,0)) == NULL)
- Cleanup("Error: couldn't open math library\n");
- if ((MathTransBase = OpenLibrary(tmath,0)) == NULL)
- Cleanup("Error: couldn't open math transform library\n");
-
- if ((screen =
- (struct Screen *)XOpenScreen("Simple Screen", HIRES, Depth)) == NULL)
- Cleanup("Error: couldn't open custom screen\n");
- newwindow.Screen = screen;
- if ((window = (struct Window *)OpenWindow(&newwindow)) == NULL)
- Cleanup("Error: couldn't open window\n");
- DrawRP = window->RPort;
- DrawVP = &screen->ViewPort;
- reset:
- gadgflag = 1;
- add_gadgets(screen);
- /* setcolors(DrawVP,colors); (A function to replace all this...) */
- SetRGB4(DrawVP, 0, 0, 0, 0);
- SetRGB4(DrawVP, 1, 15, 15, 15);
- SetRGB4(DrawVP, 2, 15, 0, 0);
- SetRGB4(DrawVP, 3, 0, 15, 0);
- SetRGB4(DrawVP, 4, 14, 3, 0);
- SetRGB4(DrawVP, 5, 15, 11, 0);
- SetRGB4(DrawVP, 6, 15, 15, 2);
- SetRGB4(DrawVP, 7, 15, 15, 15);
- SetRGB4(DrawVP, 8, 7, 13, 15);
- SetRGB4(DrawVP, 9, 11, 15, 0);
- SetRGB4(DrawVP, 10, 5, 13, 0);
- SetRGB4(DrawVP, 11, 12, 0, 14);
- SetRGB4(DrawVP, 12, 15, 2, 14);
- SetRGB4(DrawVP, 13, 15, 4, 10);
- SetRGB4(DrawVP, 14, 15, 6, 6);
- SetRGB4(DrawVP, 15, 15, 8, 2);
- SetAPen(DrawRP, color);
- SetDrMd(DrawRP, JAM2);
-
- /* Is the gadget window showing? */
-
- while (gadgflag) {
- /* Wait for something to happen. */
- Wait((1<<window->UserPort->mp_SigBit) |
- (1<<g_window->UserPort->mp_SigBit));
- while (message = (struct IntuiMessage *)GetMsg(window->UserPort)) {
- /* Something happened in the main pattern window. */
- class = message->Class;
- switch (class) {
- case CLOSEWINDOW: /* We are all done */
- ReplyMsg(message);
- Cleanup(NULL);
- case MOUSEBUTTONS:
- mcode = message->Code;
- if(mcode == SELECTDOWN) { /* The user wants to set the TLC */
- if(xoff == 0) break;
- tlcx = message->MouseX;
- tlcy = message->MouseY;
- boxon = 1;
- boxx = -1;
- SetDrMd(DrawRP,COMPLEMENT);
- }
- else if(mcode == SELECTUP) { /* The user has defined the box */
- Move(DrawRP,tlcx,tlcy); /* redraw (erase) old box */
- Draw(DrawRP,tlcx,boxy);
- Draw(DrawRP,boxx,boxy);
- Draw(DrawRP,boxx,tlcy);
- Draw(DrawRP,tlcx,tlcy);
- brcx = message->MouseX;
- brcy = message->MouseY;
- SetDrMd(DrawRP,JAM2);
- boxon = 0;
- xmax = ((float) (brcx-320.)/xscale) + xoff;
- xmin = ((float) (tlcx-320.)/xscale) + xoff;
- ymax = ((float) (brcy-100.)/(f1*xscale)) + yoff;
- ymin = ((float) (tlcy-100.)/(f1*xscale)) + yoff;
- x = 0;
- y = 0;
- xscale = 640./(xmax - xmin);
- xoff = (xmax + xmin)/2.;
- yoff = (ymax + ymin)/2.;
- scaled = 1;
- SetAPen(DrawRP,0);
- RectFill(DrawRP,0,0,640,200);
- }
- break;
- case MOUSEMOVE: /* If boxon, draw box, else ignore */
- if(boxon) {
- if(boxx >= 0) {
- Move(DrawRP,tlcx,tlcy); /* redraw (erase) old box */
- Draw(DrawRP,tlcx,boxy);
- Draw(DrawRP,boxx,boxy);
- Draw(DrawRP,boxx,tlcy);
- Draw(DrawRP,tlcx,tlcy);
- }
- boxx = message->MouseX;
- boxy = message->MouseY;
- Move(DrawRP,tlcx,tlcy); /* draw new box */
- Draw(DrawRP,tlcx,boxy);
- Draw(DrawRP,boxx,boxy);
- Draw(DrawRP,boxx,tlcy);
- Draw(DrawRP,tlcx,tlcy);
- }
- break;
- }
- ReplyMsg(message);
- }
- while (message = (struct IntuiMessage *)GetMsg(g_window->UserPort)) {
- /* Something happened in the gadget window. */
- if (message->Class == GADGETUP) {
- if (sscanf(input,"%f,%f,%f,%d", &a, &b, &c, &num) != 4) {
- sprintf(input,"Error scanning input. Reenter.");
- Move(GadgRP,10,20);
- Text(GadgRP,input,sizeof(input));
- }
- else {
- if(savea != a || saveb != b || savec != c) {
- /* At least one of the inputs has changed. Reset everything. */
- x = 0;
- y = 0;
- SetAPen(DrawRP,0);
- RectFill(DrawRP,0,0,640,200); /* erases screen */
- scaled = 0;
- }
- gadgflag = 0;
- savea = a;
- saveb = b;
- savec = c;
- }
- }
- ReplyMsg(message);
- }
- }
-
- if (g_window) CloseWindow(g_window);
- g_window = NULL;
- myInit(a, b, c, &xscale, &xoff, &yoff);
- dif = num/12;
-
- /* This is the main loop. Everything in here should be FFP or integer */
- /* First load up FFP variables. */
- affp.f = a;
- bffp.f = b;
- cffp.f = c;
- xscffp.f = xscale;
- xoffp.f = xoff;
- yoffp.f = yoff;
- f1ffp.f = f1;
- xffp.f = x;
- yffp.f = y;
- affp.i = SPFieee(affp.i);
- bffp.i = SPFieee(bffp.i);
- cffp.i = SPFieee(cffp.i);
- xffp.i = SPFieee(xffp.i);
- yffp.i = SPFieee(yffp.i);
- xscffp.i = SPFieee(xscffp.i);
- xoffp.i = SPFieee(xoffp.i);
- yoffp.i = SPFieee(yoffp.i);
- f1ffp.i = SPFieee(f1ffp.i);
-
- /* Now do loop */
- for (i = 1; i < num; i++) {
- color = (i/dif)+4;
- SetAPen(DrawRP,color);
- x0 = 320 + (int) SPTieee(SPMul(SPSub(xoffp.i,xffp.i),xscffp.i));
- y0 = 100 + (int) SPTieee(SPMul(SPMul(f1ffp.i,xscffp.i),
- SPSub(yoffp.i,yffp.i)));
- WritePixel(DrawRP, x0, y0);
- xx.i = SPSub( SPMul(Sign(xffp.i), SPSqrt(SPAbs(
- SPSub(cffp.i,SPMul(bffp.i,xffp.i))))),yffp.i);
- yy.i = SPSub(xffp.i,affp.i);
- xffp.i = xx.i;
- yffp.i = yy.i;
- while (message = (struct IntuiMessage *)GetMsg(window->UserPort)) {
- if (message->Class == CLOSEWINDOW) {
- ReplyMsg(message);
- Cleanup(NULL);
- }
- ReplyMsg(message);
- }
- }
- /* Done with loop, now convert final x, y from FFP to float */
- x = SPTieee(xffp.i);
- y = SPTieee(yffp.i);
- goto reset;
- }
-
- Sign(x)
- /* The sign bit of an FFP number is in bit 7. It is 0 for positive,
- and 1 for negative. */
- int x;
- {
- FFP xp;
- BYTE signbit;
-
- signbit = (x & 0x80L) >> 7;
- if (signbit) {
- xp.f = -1;
- xp.i = SPFieee(xp.i);
- } else {
- xp.f = 0;
- xp.i = SPFieee(xp.i);
- }
- return(xp.i); /* Returns as integer, but will be interpreted as FFP */
- }
-
- Sign2(x)
-
- float x;
- {
- int i;
-
- i = (x >= 0) ? 1 : -1 ;
- return(i);
- }
-
- myInit(a, b, c, xscale, xoff, yoff)
- /********************************************************************
- * This routine calculates the first 100 points and keeps track *
- * of the highest and lowest x and y values, then uses them for *
- * setting the scale of the screen. The screen is scaled so that *
- * the pattern takes up the middle quarter of the screen. The *
- * x scale is returned in *xscale, and the world coordinate *
- * values of the center of the screen are returned as *xoff and *
- * *yoff. *
- *******************************************************************/
- FLOAT a, b, c;
- FLOAT *xscale, *xoff, *yoff;
- {
- int i;
- FLOAT ymax = -1.e10, ymin = 1.e10;
- FLOAT xmax = -1.e10, xmin = 1.e10;
- FLOAT x = 0, y = 0;
- FLOAT xx = 0, yy = 0;
-
- if(scaled) return(0);
- for (i = 0; i < 100; i++) {
- xx = y - (FLOAT) Sign2(x) * sqrt(abs(b * x - c));
- yy = a - x;
- xmax = (xx > xmax) ? xx : xmax;
- xmin = (xx < xmin) ? xx : xmin;
- ymax = (yy > ymax) ? yy : ymax;
- ymin = (yy < ymin) ? yy : ymin;
- x = xx;
- y = yy;
- }
- /* These are the world coordinates of the center of the screen. */
- *xoff = (xmax + xmin)/2.;
- *yoff = (ymax + ymin)/2.;
- *xscale = 210./(xmax - xmin);
- /* These are for diagnostics only...
- SetAPen(DrawRP,4);
- sprintf(outtext,"xx = %f, xn = %f, yx = %f, yn = %f",xmax,xmin,ymax,ymin);
- Move(DrawRP, 10, 100);
- Text(DrawRP,outtext,sizeof(outtext));
- sprintf(outtext,"xo=%f, yo=%f, xsc=%f",*xoff,*yoff,*xscale);
- Move(DrawRP, 10, 110);
- Text(DrawRP,outtext,sizeof(outtext));
- */
- return(0);
- }
-
-
- Cleanup (ExitText)
-
- char *ExitText;
- {
- if (g_window) CloseWindow(g_window);
- if (window) CloseWindow(window);
- if (screen) CloseScreen(screen);
- if (GfxBase) CloseLibrary(GfxBase);
- if (MathBase) CloseLibrary(MathBase);
- if (MathTransBase) CloseLibrary(MathTransBase);
- if (ExitText) fprintf(stderr, ExitText);
- exit (!!ExitText); /* NULL returns 0, all else returns 1 */
- }
-
- void add_gadgets(Screen)
-
- /* Open gadget window, complete with string gadget. */
-
- struct Screen *Screen;
- {
- static char undo[40] = "";
-
- static struct IntuiText help_text = {
- 0, 1, JAM2,
- 4, -10, NULL,
- "Enter four numbers a, b, c, num",
- NULL
- };
-
- static struct StringInfo hslstring = {
- input, undo, /* input string and undo string */
- 0, sizeof(input), /* initial and max cursor position */
- 0, /* position of first displayed char */
- 0, 0, sizeof(input), 0, 0, NULL, 0, NULL
- };
-
- static struct Gadget input_gadget = {
- NULL, 10, 20, 320, 10, GADGHCOMP,
- RELVERIFY, STRGADGET, NULL, NULL,
- &help_text, NULL, (APTR)&hslstring, 0, NULL
- };
-
- static struct NewWindow gadget_window = {
- 100, 50, 420, 30, -1, -1, GADGETUP | GADGETDOWN,
- WINDOWDEPTH | WINDOWDRAG | SMART_REFRESH,
- &input_gadget, NULL, "Input",
- NULL, NULL, 0, 0, 0, 0,
- CUSTOMSCREEN
- };
-
- gadget_window.Screen = Screen;
- if ((g_window = (struct Window *)OpenWindow(&gadget_window)) == NULL)
- Cleanup("Could not open gadget window.");
- }
-
-